"""
Report Generation Module

Generates assessment reports in multiple formats (JSON, HTML, PDF).
"""

import json
import os
from datetime import datetime
from typing import Dict, List
import numpy as np
import logging

logger = logging.getLogger(__name__)


class ReportGenerator:
    """
    Generates comprehensive assessment reports.
    """

    def __init__(self, output_dir: str = "./outputs"):
        """
        Initialize report generator.

        Args:
            output_dir: Base directory for output reports
        """
        self.output_dir = output_dir
        os.makedirs(output_dir, exist_ok=True)

    def generate_json_report(self,
                            session_id: str,
                            segments_results: List[Dict],
                            metadata: Dict = None) -> Dict:
        """
        Generate JSON format report.

        Args:
            session_id: Unique session identifier
            segments_results: List of segment evaluation results
            metadata: Additional metadata (patient info, video info, etc.)

        Returns:
            Report dictionary
        """
        # Calculate overall statistics
        if segments_results:
            overall_score = np.mean([seg['final_score'] for seg in segments_results])
            overall_similarity = np.mean([seg['similarity_score'] for seg in segments_results])
            overall_geometric = np.mean([seg['geometric_score'] for seg in segments_results])
            overall_attribute = np.mean([seg['attribute_score'] for seg in segments_results])
        else:
            overall_score = 0.0
            overall_similarity = 0.0
            overall_geometric = 0.0
            overall_attribute = 0.0

        report = {
            'session_id': session_id,
            'generated_at': datetime.now().isoformat(),
            'overall_score': float(overall_score),
            'overall_similarity': float(overall_similarity),
            'overall_geometric': float(overall_geometric),
            'overall_attribute': float(overall_attribute),
            'num_segments': len(segments_results),
            'segments': [],
            'metadata': metadata or {}
        }

        # Add segment details
        for i, seg_result in enumerate(segments_results):
            segment_info = {
                'segment_id': i,
                'action_type': seg_result.get('action_type', 'unknown'),
                'frame_range': seg_result.get('frame_range', [0, 0]),
                'scores': {
                    'final_score': float(seg_result['final_score']),
                    'similarity_score': float(seg_result['similarity_score']),
                    'geometric_score': float(seg_result['geometric_score']),
                    'attribute_score': float(seg_result['attribute_score']),
                },
                'detailed_metrics': {
                    'rom_scores': seg_result.get('rom_scores', {}),
                    'speed_score': float(seg_result.get('speed_score', 0)),
                    'stability_score': float(seg_result.get('stability_score', 0)),
                    'symmetry_scores': seg_result.get('symmetry_scores', {})
                },
                'phase_scores': seg_result.get('phase_scores', {})
            }
            report['segments'].append(segment_info)

        # Generate recommendations
        report['recommendations'] = self._generate_recommendations(segments_results)

        return report

    def save_json_report(self, report: Dict, session_id: str) -> str:
        """
        Save JSON report to file.

        Args:
            report: Report dictionary
            session_id: Session identifier

        Returns:
            Path to saved report file
        """
        session_dir = os.path.join(self.output_dir, session_id)
        os.makedirs(session_dir, exist_ok=True)

        report_path = os.path.join(session_dir, 'report.json')

        with open(report_path, 'w', encoding='utf-8') as f:
            json.dump(report, f, indent=2, ensure_ascii=False)

        logger.info(f"Saved JSON report: {report_path}")

        return report_path

    def generate_html_report(self, report: Dict) -> str:
        """
        Generate HTML format report.

        Args:
            report: Report dictionary from generate_json_report

        Returns:
            HTML string
        """
        html = f"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>康复评估报告 - {report['session_id']}</title>
    <style>
        body {{
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f5f5f5;
        }}
        .header {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            border-radius: 10px;
            margin-bottom: 30px;
        }}
        .header h1 {{
            margin: 0 0 10px 0;
        }}
        .header p {{
            margin: 5px 0;
            opacity: 0.9;
        }}
        .summary {{
            background: white;
            padding: 25px;
            border-radius: 10px;
            margin-bottom: 20px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }}
        .score-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-top: 20px;
        }}
        .score-card {{
            background: #f8f9fa;
            padding: 20px;
            border-radius: 8px;
            text-align: center;
        }}
        .score-value {{
            font-size: 36px;
            font-weight: bold;
            margin: 10px 0;
        }}
        .score-label {{
            color: #666;
            font-size: 14px;
        }}
        .excellent {{ color: #10b981; }}
        .good {{ color: #3b82f6; }}
        .fair {{ color: #f59e0b; }}
        .poor {{ color: #ef4444; }}
        .segment {{
            background: white;
            padding: 20px;
            border-radius: 10px;
            margin-bottom: 15px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }}
        .segment-header {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding-bottom: 15px;
            border-bottom: 2px solid #eee;
        }}
        .metrics {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
            gap: 15px;
            margin-top: 15px;
        }}
        .metric {{
            background: #f8f9fa;
            padding: 15px;
            border-radius: 5px;
        }}
        .metric-label {{
            font-size: 12px;
            color: #666;
            margin-bottom: 5px;
        }}
        .metric-value {{
            font-size: 24px;
            font-weight: bold;
        }}
        .recommendations {{
            background: #fef3c7;
            padding: 20px;
            border-radius: 10px;
            margin-top: 20px;
            border-left: 4px solid #f59e0b;
        }}
        .recommendations h3 {{
            margin-top: 0;
            color: #92400e;
        }}
        .recommendations ul {{
            margin: 10px 0;
            padding-left: 20px;
        }}
        .recommendations li {{
            margin: 8px 0;
            color: #78350f;
        }}
    </style>
</head>
<body>
    <div class="header">
        <h1>康复动作评估报告</h1>
        <p><strong>会话ID:</strong> {report['session_id']}</p>
        <p><strong>生成时间:</strong> {report['generated_at']}</p>
        <p><strong>评估段数:</strong> {report['num_segments']}</p>
    </div>

    <div class="summary">
        <h2>综合评分</h2>
        <div class="score-grid">
            <div class="score-card">
                <div class="score-label">总体评分</div>
                <div class="score-value {self._get_score_class(report['overall_score'])}">{report['overall_score']:.1f}</div>
            </div>
            <div class="score-card">
                <div class="score-label">特征相似度</div>
                <div class="score-value {self._get_score_class(report['overall_similarity'])}">{report['overall_similarity']:.1f}</div>
            </div>
            <div class="score-card">
                <div class="score-label">几何得分</div>
                <div class="score-value {self._get_score_class(report['overall_geometric'])}">{report['overall_geometric']:.1f}</div>
            </div>
            <div class="score-card">
                <div class="score-label">属性得分</div>
                <div class="score-value {self._get_score_class(report['overall_attribute'])}">{report['overall_attribute']:.1f}</div>
            </div>
        </div>
    </div>

    <h2>分段评估</h2>
"""

        # Add segment details
        for seg in report['segments']:
            scores = seg['scores']
            metrics = seg['detailed_metrics']

            html += f"""
    <div class="segment">
        <div class="segment-header">
            <div>
                <h3 style="margin: 0;">动作段 {seg['segment_id'] + 1}: {seg['action_type']}</h3>
                <p style="margin: 5px 0; color: #666;">帧范围: {seg['frame_range'][0]}-{seg['frame_range'][1]}</p>
            </div>
            <div class="score-value {self._get_score_class(scores['final_score'])}">{scores['final_score']:.1f}</div>
        </div>

        <div class="metrics">
            <div class="metric">
                <div class="metric-label">运动幅度 (ROM)</div>
                <div class="metric-value {self._get_score_class(metrics['rom_scores'].get('overall', 0))}">{metrics['rom_scores'].get('overall', 0):.1f}</div>
            </div>
            <div class="metric">
                <div class="metric-label">速度控制</div>
                <div class="metric-value {self._get_score_class(metrics['speed_score'])}">{metrics['speed_score']:.1f}</div>
            </div>
            <div class="metric">
                <div class="metric-label">稳定性</div>
                <div class="metric-value {self._get_score_class(metrics['stability_score'])}">{metrics['stability_score']:.1f}</div>
            </div>
            <div class="metric">
                <div class="metric-label">左右对称性</div>
                <div class="metric-value {self._get_score_class(metrics['symmetry_scores'].get('overall', 0))}">{metrics['symmetry_scores'].get('overall', 0):.1f}</div>
            </div>
        </div>
    </div>
"""

        # Add recommendations
        html += """
    <div class="recommendations">
        <h3>改进建议</h3>
        <ul>
"""
        for rec in report['recommendations']:
            html += f"            <li>{rec}</li>\n"

        html += """
        </ul>
    </div>
</body>
</html>
"""

        return html

    def save_html_report(self, report: Dict, session_id: str) -> str:
        """
        Save HTML report to file.

        Args:
            report: Report dictionary
            session_id: Session identifier

        Returns:
            Path to saved report file
        """
        session_dir = os.path.join(self.output_dir, session_id)
        os.makedirs(session_dir, exist_ok=True)

        html_content = self.generate_html_report(report)
        report_path = os.path.join(session_dir, 'report.html')

        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(html_content)

        logger.info(f"Saved HTML report: {report_path}")

        return report_path

    def _get_score_class(self, score: float) -> str:
        """Get CSS class based on score."""
        if score >= 80:
            return 'excellent'
        elif score >= 60:
            return 'good'
        elif score >= 40:
            return 'fair'
        else:
            return 'poor'

    def _generate_recommendations(self, segments_results: List[Dict]) -> List[str]:
        """
        Generate personalized recommendations based on results.

        Args:
            segments_results: List of segment evaluation results

        Returns:
            List of recommendation strings
        """
        recommendations = []

        if not segments_results:
            return ["需要更多评估数据以生成建议"]

        # Analyze overall patterns
        avg_rom = np.mean([seg.get('rom_scores', {}).get('overall', 0) for seg in segments_results])
        avg_speed = np.mean([seg.get('speed_score', 0) for seg in segments_results])
        avg_stability = np.mean([seg.get('stability_score', 0) for seg in segments_results])
        avg_symmetry = np.mean([seg.get('symmetry_scores', {}).get('overall', 0) for seg in segments_results])

        # ROM recommendations
        if avg_rom < 60:
            recommendations.append("运动幅度不足，建议在专业指导下逐步增加关节活动范围")
        elif avg_rom > 85:
            recommendations.append("运动幅度良好，继续保持")

        # Speed recommendations
        if avg_speed < 60:
            recommendations.append("动作速度需要调整，尝试匀速控制动作，避免过快或过慢")
        elif avg_speed > 85:
            recommendations.append("速度控制良好，节奏感掌握到位")

        # Stability recommendations
        if avg_stability < 60:
            recommendations.append("动作稳定性需要提高，注意核心肌群控制，减少不必要的晃动")
        elif avg_stability > 85:
            recommendations.append("动作稳定性优秀，姿态控制良好")

        # Symmetry recommendations
        if avg_symmetry < 70:
            recommendations.append("左右对称性有待改善，注意两侧肢体动作协调，必要时可进行单侧强化训练")
        elif avg_symmetry > 85:
            recommendations.append("左右对称性良好，两侧协调性佳")

        # General recommendations
        if len(recommendations) == 0:
            recommendations.append("整体表现优秀，请继续保持规律训练")

        recommendations.append("建议定期进行评估，跟踪康复进度")

        return recommendations

    def generate_full_report(self,
                            session_id: str,
                            segments_results: List[Dict],
                            metadata: Dict = None,
                            formats: List[str] = None) -> Dict[str, str]:
        """
        Generate complete report in multiple formats.

        Args:
            session_id: Session identifier
            segments_results: Evaluation results
            metadata: Additional metadata
            formats: List of formats to generate ['json', 'html']

        Returns:
            Dictionary mapping format to file path
        """
        if formats is None:
            formats = ['json', 'html']

        # Generate JSON report
        report = self.generate_json_report(session_id, segments_results, metadata)

        output_paths = {}

        if 'json' in formats:
            json_path = self.save_json_report(report, session_id)
            output_paths['json'] = json_path

        if 'html' in formats:
            html_path = self.save_html_report(report, session_id)
            output_paths['html'] = html_path

        logger.info(f"Generated reports for session {session_id}: {list(output_paths.keys())}")

        return output_paths
